/*
 * max77828-private.h - Voltage regulator driver for the Maxim 77828
 *
 *  Copyright (C) 2011 Samsung Electrnoics
 *  SangYoung Son <hello.son@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __LINUX_MFD_MAX77828_PRIV_H
#define __LINUX_MFD_MAX77828_PRIV_H

#include <linux/i2c.h>

#define MAX77828_I2C_ADDR		(0x92)

#define MAX77828_NUM_IRQ_MUIC_REGS	3
#define MAX77828_REG_INVALID		(0xff)

/* pmic revision */
enum max77828_pmic_rev {
	MAX77828_REV_PASS1	= 0x00,
	MAX77828_REV_PASS2	= 0x01,
	MAX77828_REV_PASS3	= 0x02,
	MAX77828_REV_PASS4	= 0x03,
};

/* Slave addr = 0x92: PMIC/HAPTIC */
enum max77828_pmic_reg {
	MAX77828_PMIC_REG_PMICID	= 0x00,
	MAX77828_PMIC_REG_PMICREV	= 0x01,
	MAX77828_PMIC_REG_MAINCTRL1	= 0x02,
	MAX77828_PMIC_REG_MCONFIG	= 0x10,

	MAX77828_PMIC_REG_END,
};

/* Slave addr = 0x94: LED */
enum max77828_led_reg {
	MAX77828_LED_REG_STATUS1	= 0x02,
	MAX77828_LED_REG_STATUS2	= 0x03,
	MAX77828_LED_REG_I_FLASH1	= 0x04,
	MAX77828_LED_REG_I_TORCH1	= 0x05,
	MAX77828_LED_REG_MODE_SEL	= 0x06,
	MAX77828_LED_REG_FLASH_RAMP_SEL	= 0x07,
	MAX77828_LED_REG_TORCH_RAMP_SEL	= 0x08,
	MAX77828_LED_REG_FLASH_TMR_CNTL	= 0x09,
	MAX77828_LED_REG_TORCH_TMR_CNTL	= 0x0A,
	MAX77828_LED_REG_MAXFLASH1	= 0x0B,
	MAX77828_LED_REG_MAXFLASH2	= 0x0C,
	MAX77828_LED_REG_MAXFLASH3	= 0x0D,
	MAX77828_LED_REG_DCDC_CNTL1	= 0x0E,
	MAX77828_LED_REG_DCDC_CNTL2	= 0x0F,
	MAX77828_LED_REG_DCDC_ILIM	= 0x10,
	MAX77828_LED_REG_DCDC_OUT	= 0x11,
	MAX77828_LED_REG_DCDC_OUT_MAX	= 0x12,

	MAX77828_LED_REG_LEDEN		= 0x30,
	MAX77828_LED_REG_LED0BRT	= 0x31,
	MAX77828_LED_REG_LED1BRT	= 0x32,
	MAX77828_LED_REG_LED2BRT	= 0x33,
	MAX77828_LED_REG_LED3BRT	= 0x34,
	MAX77828_LED_REG_LEDBLNK	= 0x35,
	MAX77828_LED_REG_LEDRMP		= 0x36,

	MAX77828_LEG_REG_END,
};

/* Slave addr = 0x4A: MUIC */
enum max77828_muic_reg {
	MAX77828_MUIC_REG_ID		= 0x00,
	MAX77828_MUIC_REG_INT1		= 0x01,
	MAX77828_MUIC_REG_INT2		= 0x02,
	MAX77828_MUIC_REG_INT3		= 0x03,
	MAX77828_MUIC_REG_STATUS1	= 0x04,
	MAX77828_MUIC_REG_STATUS2	= 0x05,
	MAX77828_MUIC_REG_STATUS3	= 0x06,
	MAX77828_MUIC_REG_INTMASK1	= 0x07,
	MAX77828_MUIC_REG_INTMASK2	= 0x08,
	MAX77828_MUIC_REG_INTMASK3	= 0x09,
	MAX77828_MUIC_REG_CDETCTRL1	= 0x0A,
	MAX77828_MUIC_REG_CDETCTRL2	= 0x0B,
	MAX77828_MUIC_REG_CTRL1		= 0x0C,
	MAX77828_MUIC_REG_CTRL2		= 0x0D,
	MAX77828_MUIC_REG_CTRL3		= 0x0E,
	MAX77828_MUIC_REG_CTRL4		= 0x16,
	MAX77828_MUIC_REG_HVCTRL1	= 0x17,
	MAX77828_MUIC_REG_HVCTRL2	= 0x18,
	MAX77828_MUIC_REG_HVTXBYTE	= 0x19,
	MAX77828_MUIC_REG_HVRXBYTE1	= 0x1A,
	MAX77828_MUIC_REG_HVRXBYTE2	= 0x1B,
	MAX77828_MUIC_REG_HVRXBYTE3	= 0x1C,
	MAX77828_MUIC_REG_HVRXBYTE4	= 0x1D,
	MAX77828_MUIC_REG_HVRXBYTE5	= 0x1E,
	MAX77828_MUIC_REG_HVRXBYTE6	= 0x1F,
	MAX77828_MUIC_REG_HVRXBYTE7	= 0x20,
	MAX77828_MUIC_REG_HVRXBYTE8	= 0x21,
	MAX77828_MUIC_REG_HVRXBYTE9	= 0x22,
	MAX77828_MUIC_REG_HVRXBYTE10	= 0x23,
	MAX77828_MUIC_REG_HVRXBYTE11	= 0x24,
	MAX77828_MUIC_REG_HVRXBYTE12	= 0x25,
	MAX77828_MUIC_REG_HVRXBYTE13	= 0x26,
	MAX77828_MUIC_REG_HVRXBYTE14	= 0x27,
	MAX77828_MUIC_REG_HVRXBYTE15	= 0x28,
	MAX77828_MUIC_REG_HVRXBYTE16	= 0x29,

	MAX77828_MUIC_REG_END,
};

/* MAX77828 REGISTER ENABLE or DISABLE bit */
#define MAX77828_ENABLE_BIT 1
#define MAX77828_DISABLE_BIT 0

/* MAX77828 STATUS1 register */
#define STATUS1_ADC_SHIFT		0
#define STATUS1_ADCERR_SHIFT		6
#define STATUS1_ADC1K_SHIFT		7
#define STATUS1_ADC_MASK		(0x1F << STATUS1_ADC_SHIFT)
#define STATUS1_ADCERR_MASK		(0x1 << STATUS1_ADCERR_SHIFT)
#define STATUS1_ADC1K_MASK		(0x1 << STATUS1_ADC1K_SHIFT)

/* MAX77828 STATUS2 register */
#define STATUS2_CHGTYP_SHIFT		0
#define STATUS2_CHGDETRUN_SHIFT		3
#define STATUS2_DCDTMR_SHIFT		4
#define STATUS2_DXOVP_SHIFT		5
#define STATUS2_VBVOLT_SHIFT		6
#define STATUS2_CHGTYP_MASK		(0x7 << STATUS2_CHGTYP_SHIFT)
#define STATUS2_CHGDETRUN_MASK		(0x1 << STATUS2_CHGDETRUN_SHIFT)
#define STATUS2_DCDTMR_MASK		(0x1 << STATUS2_DCDTMR_SHIFT)
#define STATUS2_DXOVP_MASK		(0x1 << STATUS2_DXOVP_SHIFT)
#define STATUS2_VBVOLT_MASK		(0x1 << STATUS2_VBVOLT_SHIFT)

/* MAX77828 STATUS3 register */
#define STATUS3_VBADC_SHIFT		0
#define STATUS3_VDNMON_SHIFT		4
#define STATUS3_DNRES_SHIFT		5
#define STATUS3_MPNACK_SHIFT		6
#define STATUS3_VBADC_MASK		(0x1 << STATUS3_VBADC_SHIFT)
#define STATUS3_VDNMON_MASK		(0x1 << STATUS3_VDNMON_SHIFT)
#define STATUS3_DNRES_MASK		(0x1 << STATUS3_DNRES_SHIFT)
#define STATUS3_MPNACK_MASK		(0x1 << STATUS3_MPNACK_SHIFT)

/* MAX77828 CDETCTRL1 register */
#define CDETCTRL1_CHGDETEN_SHIFT	0
#define CDETCTRL1_CHGTYPM_SHIFT		1
#define CDETCTRL1_DCDEN_SHIFT		2
#define CDETCTRL1_DCD2SCT_SHIFT		3
#define CDETCTRL1_CDDELAY_SHIFT		4
#define CDETCTRL1_DCDCPL_SHIFT		5
#define CDETCTRL1_CDPDET_SHIFT		7
#define CDETCTRL1_CHGDETEN_MASK		(0x1 << CDETCTRL1_CHGDETEN_SHIFT)
#define CDETCTRL1_CHGTYPM_MASK		(0x1 << CDETCTRL1_CHGTYPM_SHIFT)
#define CDETCTRL1_DCDEN_MASK		(0x1 << CDETCTRL1_DCDEN_SHIFT)
#define CDETCTRL1_DCD2SCT_MASK		(0x1 << CDETCTRL1_DCD2SCT_SHIFT)
#define CDETCTRL1_CDDELAY_MASK		(0x1 << CDETCTRL1_CDDELAY_SHIFT)
#define CDETCTRL1_DCDCPL_MASK		(0x1 << CDETCTRL1_DCDCPL_SHIFT)
#define CDETCTRL1_CDPDET_MASK		(0x1 << CDETCTRL1_CDPDET_SHIFT)

/* MAX77828 CONTROL1 register */
#define CTRL1_COMN1SW_SHIFT		0
#define CTRL1_COMP2SW_SHIFT		3
#define CTRL1_IDBEN_SHIFT		7
#define CTRL1_COMN1SW_MASK		(0x7 << CTRL1_COMN1SW_SHIFT)
#define CTRL1_COMP2SW_MASK		(0x7 << CTRL1_COMP2SW_SHIFT)
#define CTRL1_IDBEN_MASK		(0x1 << CTRL1_IDBEN_SHIFT)

/* MAX77828 CONTROL2 register */
#define CTRL2_LOWPWD_SHIFT		0
#define CTRL2_ADCEN_SHIFT		1
#define CTRL2_CPEn_SHIFT		2
#define CTRL2_SFOUTASRT_SHIFT		3
#define CTRL2_SFOUTORD_SHIFT		4
#define CTRL2_ACCDET_SHIFT		5
#define CTRL2_USBCPINT_SHIFT		6
#define CTRL2_RCPS_SHIFT		7
#define CTRL2_LOWPWD_MASK		(0x1 << CTRL2_LOWPWD_SHIFT)
#define CTRL2_ADCEN_MASK		(0x1 << CTRL2_ADCEN_SHIFT)
#define CTRL2_CPEn_MASK			(0x1 << CTRL2_CPEn_SHIFT)
#define CTRL2_SFOUTASRT_MASK		(0x1 << CTRL2_SFOUTASRT_SHIFT)
#define CTRL2_SFOUTORD_MASK		(0x1 << CTRL2_SFOUTORD_SHIFT)
#define CTRL2_ACCDET_MASK		(0x1 << CTRL2_ACCDET_SHIFT)
#define CTRL2_USBCPINT_MASK		(0x1 << CTRL2_USBCPINT_SHIFT)
#define CTRL2_RCPS_MASK			(0x1 << CTRL2_RCPS_SHIFT)

#define CTRL2_CPEn1_LOWPWD0	((MAX77828_ENABLE_BIT << CTRL2_CPEn_SHIFT) | \
				(MAX77828_DISABLE_BIT << CTRL2_LOWPWD_SHIFT))
#define CTRL2_CPEn0_LOWPWD1	((MAX77828_DISABLE_BIT << CTRL2_CPEn_SHIFT) | \
				(MAX77828_ENABLE_BIT << CTRL2_LOWPWD_SHIFT))

/* MAX77828 CONTROL3 register */
#define CTRL3_JIGSET_SHIFT		0
#define CTRL3_JIGSET_MASK		(0x3 << CTRL3_JIGSET_SHIFT)

/* MAX77828 CONTROL4 register */
#define CTRL4_ADCDBSET_SHIFT		0
#define CTRL4_USBAUTO_SHIFT		4
#define CTRL4_FCTAUTO_SHIFT		5
#define CTRL4_ADCMODE_SHIFT		6
#define CTRL4_ADCDBSET_MASK		(0x03 << CTRL4_ADCDBSET_SHIFT)
#define CTRL4_USBAUTO_MASK		(0x01 << CTRL4_USBAUTO_SHIFT)
#define CTRL4_FCTAUTO_MASK		(0x01 << CTRL4_FCTAUTO_SHIFT)
#define CTRL4_ADCMODE_MASK		(0x03 << CTRL4_ADCMODE_SHIFT)

/* MAX77828 HVCONTROL1 register */
#define HVCTRL1_DPDNVDEN_SHIFT		0
#define HVCTRL1_DNVD_SHIFT		1
#define HVCTRL1_DPVD_SHIFT		3
#define HVCTRL1_VBUSADCEN_SHIFT		5
#define HVCTRL1_DPDNVDEN_MASK		(0x1 << HVCTRL1_DPDNVDEN_SHIFT)
#define HVCTRL1_DNVD_MASK		(0x3 << HVCTRL1_DNVD_SHIFT)
#define HVCTRL1_DPVD_MASK		(0x3 << HVCTRL1_DPVD_SHIFT)
#define HVCTRL1_DPVD_D06 		(0x2 << HVCTRL1_DPVD_SHIFT)

/* MAX77828 HVCONTROL2 register*/
#define HVCTRL2_HVDIGEN_SHIFT		0
#define HVCTRL2_DP06EN_SHIFT		1
#define HVCTRL2_DNRESEN_SHIFT		2
#define HVCTRL2_MPING_SHIFT		3
#define HVCTRL2_MTXEN_SHIFT		4
#define HVCTRL2_MTXBUSRES_SHIFT		5
#define HVCTRL2_MPINGENB_SHIFT		6
#define HVCTRL2_HVDIGEN_MASK		(0x1 << HVCTRL2_HVDIGEN_SHIFT)
#define HVCTRL2_DP06EN_MASK		(0x1 << HVCTRL2_DP06EN_SHIFT)
#define HVCTRL2_DNRESEN_MASK		(0x1 << HVCTRL2_DNRESEN_SHIFT)
#define HVCTRL2_MPING_MASK		(0x1 << HVCTRL2_MPING_SHIFT)
#define HVCTRL2_MTXEN_MASK		(0x1 << HVCTRL2_MTXEN_SHIFT)
#define HVCTRL2_MTXBUSRES_MASK		(0x1 << HVCTRL2_MTXBUSRES_SHIFT)
#define HVCTRL2_MPINGENB_MASK		(0x1 << HVCTRL2_MPINGENB_SHIFT)

/* Interrupt 1 */
#define INT_DETACH		(0x1 << 1)
#define INT_ATTACH		(0x1 << 0)

/* muic register value for COMN1, COMN2 in CTRL1 reg  */
enum max77828_reg_ctrl1_val {
	MAX77828_MUIC_CTRL1_BIN_0_000 = 0x00,
	MAX77828_MUIC_CTRL1_BIN_1_001 = 0x01,
	MAX77828_MUIC_CTRL1_BIN_2_010 = 0x02,
	MAX77828_MUIC_CTRL1_BIN_3_011 = 0x03,
	MAX77828_MUIC_CTRL1_BIN_4_100 = 0x04,
	MAX77828_MUIC_CTRL1_BIN_5_101 = 0x05,
	MAX77828_MUIC_CTRL1_BIN_6_110 = 0x06,
	MAX77828_MUIC_CTRL1_BIN_7_111 = 0x07,
};

enum max77828_switch_sel_val {
	MAX77828_SWITCH_SEL_1st_BIT_USB		= 0x1 << 0,
	MAX77828_SWITCH_SEL_2nd_BIT_UART	= 0x1 << 1,
};

enum max77828_reg_ctrl1_type {
	CTRL1_AP_USB =
		(MAX77828_MUIC_CTRL1_BIN_1_001 << CTRL1_COMP2SW_SHIFT)
		| MAX77828_MUIC_CTRL1_BIN_1_001 ,
	CTRL1_AUDIO =
		(MAX77828_MUIC_CTRL1_BIN_2_010 << CTRL1_COMP2SW_SHIFT)
		| MAX77828_MUIC_CTRL1_BIN_2_010 ,
	CTRL1_CP_USB =
		(MAX77828_MUIC_CTRL1_BIN_4_100 << CTRL1_COMP2SW_SHIFT)
		| MAX77828_MUIC_CTRL1_BIN_4_100 ,
	CTRL1_AP_UART =
		(MAX77828_MUIC_CTRL1_BIN_3_011 << CTRL1_COMP2SW_SHIFT)
		| MAX77828_MUIC_CTRL1_BIN_3_011 ,
	CTRL1_CP_UART =
		(MAX77828_MUIC_CTRL1_BIN_5_101 << CTRL1_COMP2SW_SHIFT)
		| MAX77828_MUIC_CTRL1_BIN_5_101 ,
};
/*TODO must modify H/W rev.5*/

enum max77828_irq_source {
	LED_INT = 0,
	TOPSYS_INT,
	CHG_INT,
	MUIC_INT1,
	MUIC_INT2,
	MUIC_INT3,

	MAX77828_IRQ_GROUP_NR,
};

enum max77828_irq {
	/* MUIC INT1 */
	MAX77828_MUIC_IRQ_INT1_ADC,
	MAX77828_MUIC_IRQ_INT1_RSVD,
	MAX77828_MUIC_IRQ_INT1_ADCERR,
	MAX77828_MUIC_IRQ_INT1_ADC1K,

	/* MUIC INT2 */
	MAX77828_MUIC_IRQ_INT2_CHGTYP,
	MAX77828_MUIC_IRQ_INT2_CHGDETREUN,
	MAX77828_MUIC_IRQ_INT2_DCDTMR,
	MAX77828_MUIC_IRQ_INT2_DXOVP,
	MAX77828_MUIC_IRQ_INT2_VBVOLT,

	/* MUIC INT3 */
	MAX77828_MUIC_IRQ_INT3_VBADC,
	MAX77828_MUIC_IRQ_INT3_VDNMON,
	MAX77828_MUIC_IRQ_INT3_DNRES,
	MAX77828_MUIC_IRQ_INT3_MPNACK,
	MAX77828_MUIC_IRQ_INT3_MRXBUFOW,
	MAX77828_MUIC_IRQ_INT3_MRXTRF,
	MAX77828_MUIC_IRQ_INT3_MRXPERR,
	MAX77828_MUIC_IRQ_INT3_MRXRDY,

	MAX77828_IRQ_NR,
};

struct max77828_dev {
	struct device *dev;
	struct i2c_client *i2c; /* 0x92; Haptic, pmic */
	struct i2c_client *muic; /* 0x4A; MUIC */
	struct i2c_client *led; /* 0x94; LED */
	struct mutex iolock;

	int type;

	int irq;
	int irq_base;
	int irq_gpio;
	bool wakeup;
	struct mutex irqlock;
	int irq_masks_cur[MAX77828_IRQ_GROUP_NR];
	int irq_masks_cache[MAX77828_IRQ_GROUP_NR];

#ifdef CONFIG_HIBERNATION
	/* For hibernation */
	u8 reg_pmic_dump[MAX77828_PMIC_REG_END];
	u8 reg_muic_dump[MAX77828_MUIC_REG_END];
	u8 reg_led_dump[MAX77828_LED_REG_END];
#endif

	/* pmic revision */
	u8 pmic_rev;	/* REV */
	u8 pmic_ver;	/* VERSION */

	struct max77828_platform_data *pdata;
};

enum max77828_types {
	TYPE_MAX77828,
};

extern struct device *switch_dev;
extern int max77828_irq_init(struct max77828_dev *max77828);
extern void max77828_irq_exit(struct max77828_dev *max77828);
extern int max77828_irq_resume(struct max77828_dev *max77828);

extern int max77828_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
extern int max77828_bulk_read(struct i2c_client *i2c, u8 reg, int count,
				u8 *buf);
extern int max77828_write_reg(struct i2c_client *i2c, u8 reg, u8 value);
extern int max77828_bulk_write(struct i2c_client *i2c, u8 reg, int count,
				u8 *buf);
extern int max77828_update_reg(struct i2c_client *i2c,
				u8 reg, u8 val, u8 mask);
extern int max77828_muic_get_charging_type(void);
extern int max77828_muic_get_status1_adc1k_value(void);
extern int max77828_muic_get_status1_adc_value(void);
extern int muic_otg_control(int enable);
extern void powered_otg_control(int);
extern int max77828_muic_set_audio_switch(bool enable);

#ifdef CONFIG_MFD_MAX77828
enum cable_type_muic {
	CABLE_TYPE_NONE_MUIC = 0,		/* 0 */
	CABLE_TYPE_USB_MUIC,			/* 1 */
	CABLE_TYPE_OTG_MUIC,			/* 2 */
	CABLE_TYPE_TA_MUIC,			/* 3 */
	CABLE_TYPE_HV_TA_MUIC,			/* 4 */
	CABLE_TYPE_DESKDOCK_MUIC,		/* 5 */
	CABLE_TYPE_CARDOCK_MUIC,		/* 6 */
	CABLE_TYPE_JIG_UART_OFF_MUIC,		/* 7 */
	CABLE_TYPE_JIG_UART_OFF_VB_MUIC,	/* 8 VBUS enabled */
	CABLE_TYPE_JIG_UART_ON_MUIC,		/* 9 */
	CABLE_TYPE_JIG_USB_OFF_MUIC,		/* 10 */
	CABLE_TYPE_JIG_USB_ON_MUIC,		/* 11 */
	CABLE_TYPE_MHL_MUIC,			/* 12 */
	CABLE_TYPE_MHL_VB_MUIC,			/* 13 */
	CABLE_TYPE_SMARTDOCK_MUIC,		/* 14 */
	CABLE_TYPE_SMARTDOCK_TA_MUIC,		/* 15 */
	CABLE_TYPE_SMARTDOCK_USB_MUIC,		/* 16 */
	CABLE_TYPE_AUDIODOCK_MUIC,		/* 17 */
	CABLE_TYPE_INCOMPATIBLE_MUIC,		/* 18 */
	CABLE_TYPE_CDP_MUIC,			/* 19 */
	CABLE_TYPE_HMT_MUIC,			/* 20 */
	CABLE_TYPE_HMT_TA_MUIC,			/* 21 */
#if defined(CONFIG_MUIC_DET_JACK)
	CABLE_TYPE_EARJACK_MUIC,		/* 22 */
#endif
	CABLE_TYPE_UNKNOWN_MUIC			/* 23 */
};

enum {
	AP_USB_MODE = 0,
	AUDIO_MODE,
	CP_USB_MODE,
	OPEN_USB_MODE,
};


enum usb_cable_status {
	USB_CABLE_DETACHED = 0,
	USB_CABLE_ATTACHED,
	USB_OTGHOST_DETACHED,
	USB_OTGHOST_ATTACHED,
	USB_POWERED_HOST_DETACHED,
	USB_POWERED_HOST_ATTACHED,
	USB_CABLE_DETACHED_WITHOUT_NOTI,
};

enum {
	UART_PATH_CP = 0,
	UART_PATH_AP,
};

#if defined(CONFIG_MUIC_DET_JACK)
enum {
	NOT_INIT = 0,
	INIT_START,
	INIT_DONE,
};
#endif

#endif /* CONFIG_MFD_MAX77828 */

#endif /*  __LINUX_MFD_MAX77828_PRIV_H */
